package com.linh.trade.algo;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import com.linh.trade.data.Point;

public class TrendFinder {

	private static final Logger LOG = LoggerFactory
			.getLogger(TrendFinder.class);

	private List<Point> pointsInWindow;

	private long latestTime;

	private WindowMover windowMover;

	public TrendFinder(WindowMover windowMover) {
		super();
		this.windowMover = windowMover;
		pointsInWindow = new ArrayList<Point>();
	}

	public void newPoint(Point point) {
		pointsInWindow.add(point);
		latestTime = point.getNano();
	}

	private void windowMove() {

		windowMover.move(pointsInWindow, latestTime);
		logWindow();

	}

	private void logWindow() {
		StringBuilder builder = new StringBuilder();
		builder.append(pointsInWindow.size() + " points,");
		if (pointsInWindow.size() > 0) {
			long oldest = pointsInWindow.get(0).getNano();
			long windowSize = latestTime - oldest;
			long milisecs = windowSize / 1000000;
			builder.append("window time=" + windowSize + " nanosec or "
					+ milisecs + " milisecs ,");
		}
		for (int i = 0; i < pointsInWindow.size(); i++) {
			Point p = pointsInWindow.get(i);
			builder.append(p.toString());
		}
		LOG.info(builder.toString());

	}

	public Trend getCurrentTrend() {
		// adjust the window
		windowMove();
		if (pointsInWindow.size() > 3) {
			double[] delta = getDelta();
			double deltaSum = getDeltaSum(delta);
			String deltaString=getDeltaString(delta);
			Trend trend=new Trend(deltaString,deltaSum);
			LOG.info(trend.toString());
			return trend;
		}

		return new Trend("", 0);
	}

	private String getDeltaString(double[] delta) {
		StringBuilder builder = new StringBuilder();
		for (int i = 0; i < delta.length; i++) {
			if (delta[i] > 0) {
				builder.append("+");
			} else if (delta[i] < 0) {
				builder.append("-");
			} else {
				builder.append("0");
			}
		}
		return builder.toString();

	}

	public double getDeltaSum(double[] delta) {
		double deltaSum = 0;

		for (int i = 0; i < delta.length; i++) {
			deltaSum += delta[i];
		}

		return deltaSum;
	}

	public double[] getDelta() {

		if (pointsInWindow.size() > 1) {
			double delta[] = new double[pointsInWindow.size() - 1];
			for (int i = 0; i < pointsInWindow.size() - 1; i++) {

				Point p1 = pointsInWindow.get(i);
				Point p2 = pointsInWindow.get(i + 1);
				delta[i] = getDelta(p1, p2);
			}
			return delta;
		}
		return new double[0];
	}

	private double getDelta(Point p1, Point p2) {
		long dt = p2.getNano() - p1.getNano();

		double dP = p2.getRate() - p1.getRate();
		if (dt != 0) {
			double ret = dP / dt;
			ret = ret * 1000000000;
			return ret;
		} else {
			return 0;
		}
	}

	int countPositive(double[] delta) {
		int count = 0;
		for (int i = delta.length - 1; i > -1; i--) {
			if (delta[i] > 0) {
				count++;
			} else {
				return count;
			}
		}
		return count;
	}

	int countNegative(double[] delta) {
		int count = 0;
		for (int i = delta.length - 1; i > -1; i--) {
			if (delta[i] < 0) {
				count++;
			} else {
				return count;
			}
		}
		return count;
	}

	public List<Point> getPointsInWindow() {
		return pointsInWindow;
	}

}
